package com.legendshop.openportal.sdk.utils;

import com.legendshop.openportal.sdk.cache.OpenCache;
import com.legendshop.openportal.sdk.config.OpenConfig;
import com.legendshop.openportal.sdk.model.OpenResult;
import com.legendshop.openportal.sdk.model.constants.CommonConstants;
import com.legendshop.openportal.sdk.model.constants.CommonStatusEnum;
import com.legendshop.openportal.sdk.model.request.AuthRequest;
import com.legendshop.openportal.sdk.model.response.AuthResponse;
import com.legendshop.openportal.sdk.registry.OpenCacheRegistry;
import com.legendshop.openportal.sdk.registry.OpenConfigProviderRegistry;
import com.legendshop.openportal.sdk.service.AuthService;

/**
 * @author jzh
 * @version 1.0.0
 * @title TokenUtil
 * @date 2024/6/17 18:43
 * @description：token工具
 */
public class TokenUtil {

    private TokenUtil() {}

    /**
     * 获取访问token
     * @return
     */
    public static OpenResult<AuthResponse> getToken() {
        OpenCache cache = OpenCacheRegistry.getCache();
        OpenConfig config = OpenConfigProviderRegistry.getProvider().getConfig();
        AuthResponse authResponse = cache.get(CommonConstants.ACCESS_TOKEN_CACHE_KEY);

        // 如果不为空，则返回
        if (authResponse != null) {
            // 这里可以加个提前的异步获取token的线程，减少token过期时并发获取token的压力
            // todo ...

            return OpenResult.success(authResponse);
        }

        // 如果缓存里没有，则获取token
        OpenResult<AuthResponse> openResult = cache.lock(CommonConstants.ACCESS_TOKEN_CACHE_KEY + "lock", () -> {
            AuthRequest authRequest = new AuthRequest();
            authRequest.setClientId(config.getClientId());
            authRequest.setClientSecret(config.getClientSecret());
            authRequest.setScope(config.getScope());
            return AuthService.getAccessToken(authRequest);
        });

        // 如果为空，说明没抢到锁，可能其它线程已经更新了
        if (openResult == null) {
            // 此时，则重新获取一下
            authResponse = cache.get(CommonConstants.ACCESS_TOKEN_CACHE_KEY);
        } else {
            // 如果不为空，则看一下有没有结果，有就更新缓存
            if (openResult.isSuccess()) {
                authResponse = openResult.getData();

                // 缓存时间减5分钟，防止由于请求和程序问题，导致的与开放平台缓存时间不一致
                cache.put(CommonConstants.ACCESS_TOKEN_CACHE_KEY, authResponse, authResponse.getExpiresIn() - 5 * 60);
            } else {

                // 如果不成功，则返回错误信息
                return openResult;
            }
        }

        // 如果还是为空，则应该是出问题了，直接返回错误
        if (authResponse == null) {
            return OpenResult.fail(CommonStatusEnum.ERROR);
        }

        return OpenResult.success(authResponse);
    }
}
